package com.gitee.l0km.beanfilter.interceptor;

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import com.facebook.swift.codec.ThriftStruct;
import com.gitee.l0km.aocache.annotations.AoWeakCacheable;
import com.gitee.l0km.casban.CasbanCachedClassScanner;
import com.gitee.l0km.casban.CountLimitStrategy;
import com.gitee.l0km.com4j.basex.annotations.ActiveOnClass;
import com.gitee.l0km.com4j.basex.annotations.ActiveOnClassSupport;
import com.gitee.l0km.common.spring.core.annotation.AnnotationUtils;
import com.gitee.l0km.xthrift.base.BaseThriftUtils;
import com.gitee.l0km.xthrift.base.ThriftDecorator;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;

import static com.gitee.l0km.casban.CommonPredicates.subtypeFilter;

/**
 * {@link ThriftDecorator}装饰类型支持工具类型
 * @author guyadong
 *
 */
@ActiveOnClass(ThriftDecorator.class)
public class ThriftDecoratorSupport {
	/**
	 * 运行时是否有 {@code xthrift-base} 标志
	 */
	public static final boolean WITH_XTHRIFT_BASE = ActiveOnClassSupport.isActive(ThriftDecoratorSupport.class);

	/**
	 * 返回所有实现了{@link ThriftDecorator}的类型
	 */
	private static Set<Class<?>> getThriftDecoratorTypes0() {
		return CasbanCachedClassScanner.getInstance().getClasses(CountLimitStrategy.ANY,
				subtypeFilter(ThriftDecorator.class));
	}

	/**
	 * 如果类型没有{@link ThriftStruct}注解则尝试查找该类型的装饰类型(实现 {@link ThriftDecorator}接口)并返回,
	 * 没有找到返回{@code null}
	 * 
	 * @param <T>
	 * @param clazz
	 */
	@SuppressWarnings("unchecked")
	private static <T> Class<? extends ThriftDecorator<T>> getThriftDecoratorOf0(Class<T> clazz) {
		if (null != clazz && null == AnnotationUtils.getAnnotation(clazz, ThriftStruct.class)) {
			return (Class<? extends ThriftDecorator<T>>) getThriftDecoratorTypes0().stream()
					.filter(decorator -> clazz.equals(BaseThriftUtils.delegateClassOf(decorator))).findFirst()
					.orElse(null);
		}
		return null;
	}

	/**
	 * @see #getThriftDecoratorOf0(Class)
	 */
	@AoWeakCacheable(expireAfterAccess = 20, expireAfterAccessTimeUnit = TimeUnit.SECONDS)
	public static <T> Class<? extends ThriftDecorator<T>> getThriftDecoratorOf(Class<T> clazz) {
		return WITH_XTHRIFT_BASE ? getThriftDecoratorOf0(clazz) : null;
	}

	/**
	 * 对于输入的类型，如果是装饰类({@link ThriftDecorator}),则转为代理类型，否则原样保留，返回转后的集合
	 * @param classes
	 */
	private static  ImmutableSet<Class<?>> delegateClasses0(Iterable<Class<?>>classes){
		LinkedHashSet<Class<?>> delegateClasses = FluentIterable.from(classes)
				.filter(Predicates.notNull())
				.transform(BaseThriftUtils::delegateClassOrSelf)
				.copyInto(new LinkedHashSet<Class<?>>());
		return ImmutableSet.copyOf(delegateClasses);
	}
	/**
	 * 将输入的类型中装饰类({@link ThriftDecorator})转为代理类型<br>
	 * @param classes 为{@code null}返回空集合
	 * @see #delegateClasses0(Iterable)
	 */
	public static  ImmutableSet<Class<?>> delegateClasses(Iterable<Class<?>>classes){
		if(null == classes) {
			return ImmutableSet.of();
		}
		return WITH_XTHRIFT_BASE  ? delegateClasses0(classes) : ImmutableSet.copyOf(classes);
	}
}
